
#ifndef _WSSOCKET_H_
#define _WSSOCKET_H_


#include "Common.h"
#include "Network/BaseSocket.h"
#include "WorldPacket.h"
#include "Resource.h"
#include "Users.h"
#include "Character.h"

#include "Threading/AtomicCounter.h"

#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>

#include "websocketpp/common/connection_hdl.hpp"

#ifndef _WEBSOCKET_DEFINE_
#define _WEBSOCKET_DEFINE_

typedef websocketpp::connection_hdl	WebSocketHandle;

#endif

#ifndef _SOCKET_DEFINE_
#define _SOCKET_DEFINE_

#define WGS_SOCKET_WRITE_MUTEX_NAME socket_write_mutex
#define WGS_SOCKET_READ_MUTEX_NAME socket_read_mutex

#define WGS_SOCKET_WRITE_MUTEX mutable boost::mutex WGS_SOCKET_WRITE_MUTEX_NAME;
#define WGS_SOCKET_READ_MUTEX mutable boost::mutex WGS_SOCKET_READ_MUTEX_NAME;

#define WGS_SOCKET_WRITE_LOCK         boost::lock_guard<boost::mutex>  wgsSocketMutexLock(WGS_SOCKET_WRITE_MUTEX_NAME);
#define WGS_SOCKET_READ_LOCK         boost::lock_guard<boost::mutex>  wgsSocketMutexLock(WGS_SOCKET_READ_MUTEX_NAME);

#define WGS_SOCKET_LOCK_MUTEX(name) boost::lock_guard<boost::mutex>  wgsSocketMutexLock(name);

#define WGS_WEBSOCKET_WRITE_MUTEX_NAME websocket_write_mutex
#define WGS_WEBSOCKET_READ_MUTEX_NAME websocket_read_mutex

#define WGS_WEBSOCKET_WRITE_MUTEX mutable boost::mutex WGS_WEBSOCKET_WRITE_MUTEX_NAME;
#define WGS_WEBSOCKET_READ_MUTEX mutable boost::mutex WGS_WEBSOCKET_READ_MUTEX_NAME;

#define WGS_WEBSOCKET_WRITE_LOCK         boost::lock_guard<boost::mutex>  wgsWebSocketMutexLock(WGS_WEBSOCKET_WRITE_MUTEX_NAME);
#define WGS_WEBSOCKET_READ_LOCK         boost::lock_guard<boost::mutex>  wgsWebSocketMutexLock(WGS_WEBSOCKET_READ_MUTEX_NAME);


#endif

class SERVER_DECL  WSSocket : public BaseSocket,public Resource
{
	void DeleteSocket();
protected:
       	void prepareImpl(void);
        /** Destroys data cached by prepareImpl.
         */
        void unprepareImpl(void);
        /// @copydoc Resource::loadImpl
        bool loadImpl(void);
        /// @copydoc Resource::postLoadImpl
        void postLoadImpl(void);

	void preUnloadImpl(void);
        /// @copydoc Resource::unloadImpl
        void unloadImpl(void);
        /// @copydoc Resource::calculateSize
        size_t calculateSize(void) const;

public:
	WGS_SOCKET_WRITE_MUTEX
	WGS_SOCKET_READ_MUTEX
	WGS_WEBSOCKET_WRITE_MUTEX
	WGS_WEBSOCKET_READ_MUTEX


	WSSocket(ResourceManager* creator, const String& name, ResourceHandle handle,
            const String& group, bool isManual = false, ManualResourceLoader* loader = 0);
        ~WSSocket();

	enum SOCKET_STATUS
        {
                SOCKET_STATUS_NONE = 0,
                SOCKET_STATUS_CONNECT = 1,
                SOCKET_STATUS_CONNECTED = 3,
                SOCKET_STATUS_ERROR = 4,
                SOCKET_STATUS_DISCONNECTING = 5,
                SOCKET_STATUS_DISCONNECT = 6
        };

        enum SOCKET_TYPE
        {
                SOCKET_TYPE_NONE        = 0,
                SOCKET_TYPE_CLIENT      = 1,
                SOCKET_TYPE_LISTEN      = 2
        };

        void OnRecvData();
        void OnSendData() {}

        void OnConnect();
        bool OnConnecting();
        void OnDisconnect();
	void OnListen();
	//void OnAccept(int fd, void * pointer);

	bool Write(const void * data, size_t bytes);
	void Accept(void);
	void Finalize(void);
	void Close(void);

	bool Listen(const char * ListenAddress, uint32 Port);

	void InitSocket(int fd, size_t readbuffersize, size_t writebuffersize, const sockaddr_in * peer);

	//继承从BaseSokcet
	bool Writable(void);
	bool WritableNotLock(void);
	bool OnRead(size_t len);
	bool OnWrite(size_t len);
	bool OnError(int errcode);
	bool OnAccept(int fd,void * pointer);
	void Disconnect();
	

	void Pong(uint32 serial);
	void TimeQuest(void);
	void TgwAck(void);

	//发送Flash 安全策略文件
	void SendFlashPolicyFile(void);

	ResourceProxy	   m_User;	//用户验证帐号
	ResourceProxy	   m_Char;    //用户当前武将（君主)

	ResourceProxy		m_uplink;   //用户连接的区域(Region)


	WGSERVER_INLINE  const SOCKET_TYPE  &  GetSocketType(void)      {       return m_socket_type; }
        WGSERVER_INLINE  void  SetSocketType(const SOCKET_TYPE & type)  {       m_socket_type = type ;  }

        WGSERVER_INLINE bool    isServerSocket(void)    {       return m_socket_type == SOCKET_TYPE_LISTEN;     }

	WGSERVER_INLINE const uint32 & getLastTimer(void)	{	return m_last_timer;	}
	WGSERVER_INLINE void setLastTimer(const uint32 & tm)	{	m_last_timer = tm;	}



	WGSERVER_INLINE const bool & isBusy(void)	{	return m_isThreadQueued;	}
	WGSERVER_INLINE void setBusy()		{	m_isThreadQueued = true;	}
	WGSERVER_INLINE void setIdle(void)	{	m_isThreadQueued = false;	}

	WGSERVER_INLINE const bool & isPacketAvailed(void)	{	return m_packetAvailed;	}
	WGSERVER_INLINE void setPacketAvailed(bool set)		{	m_packetAvailed = set;	}

	
	void	setCurrentCharacter(CharPtr & curChar);
	void	removeCurrentCharacter(void);
	CharPtr  getCurrentCharacter(void)	{	return m_Char.getResourcePtr();	}

	void	setCurrentUser(UserPtr & user);
	void	removeCurrentUser(void);
	UserPtr	 getCurrentUser(void)		{	return m_User.getResourcePtr();	}


	bool	isAuthentication(void);
	//二级密码是否登录
	bool	isSecondAuth(void)	{	return m_secondAuth;	}
	//设置2级密码是否验证
	void 	setSecondAuth(const bool & set);

	//设置二级验证时间，用于超时机制	
	const uint32 &  getSecondAuthTime(void)	{	return m_secondAuthTime;	}
	void	setSecondAuthTime(const uint32 & authTime)	{	m_secondAuthTime = authTime;	}


	bool _OutPacket(uint16 opcode, size_t len, const void* data);
	void OutPacket(uint16 opcode, size_t len, const void* data);
	void OutPacket(size_t len,const void * data);
	void SendPacket(WorldPacket* packet);
	
	/** Get IP in numerical form
         */
	const char * GetIP()	{
		const char * ip = GetFakeIP();
		if(ip == NULL)
			return GetRealIP();
		else
			return ip;
	}
	void	SetFakeIP(const char * fakeIP)		{	m_fakeIP = fakeIP;	}
	void	SetFakeIP(const String & fakeIP)	{	m_fakeIP = fakeIP;	}
	const char * GetFakeIP()	{
		if(m_fakeIP == "")
			return NULL;
		else
			return m_fakeIP.c_str();
	}
        const char * GetRealIP() { return inet_ntoa(m_addr.sin_addr); }
        unsigned int  GetNumIP() { return (unsigned int) m_addr.sin_addr.s_addr; }
        int  GetPort()  { return (int)htons(m_addr.sin_port); }


	WGSERVER_INLINE void IncSendLock() {  ++m_writeLock; }
	WGSERVER_INLINE void DecSendLock() {  --m_writeLock; }
	WGSERVER_INLINE bool HasSendLock() { return (m_writeLock.GetVal() != 0); }
	WGSERVER_INLINE void ZeroSendLock()     {       m_writeLock.SetVal(0);  }
	WGSERVER_INLINE bool AcquireSendLock()
	{
		if(m_writeLock.SetVal(1) != 0)
			return false;
		else
			return true;
	} 

	const bool & isCheckTimeOut(void)	{	return m_checkTimeout;	}
	void	setCheckTimetOut(const bool & set);
	
	//获取和设置Socket 超时时间，单位MS 默认为0 则取系统默认超时时间
	const uint32 & getTimeOutTimer(void)	{	return m_timeout_timer; }
	void setTimeOutTimer(const uint32 & set)	{	m_timeout_timer = set;	}


	const uint32 & getRunTimer(void)		{	return m_run_timer;	}
	void	setRunTimer(const uint32 & set)  	{	m_run_timer = set;	}

	//检查是否运行命令
	const bool checkRunTimerBlock(const uint32 & p_time)	{	return ((uint32)(p_time - m_last_timer))<m_run_timer?true:false;	}
	

	const size_t & getSendSize()		{	return m_sendedSize;	}
	const size_t & getRealSendSize()	{	return m_compressSize;	}
	const size_t & getReadSize()		{	return m_readSize;	}

	bool    isConnected()           {       return m_socket_status.get() == SOCKET_STATUS_CONNECTED;        }


	//Web Socket
	const WebSocketHandle & getWebSocketHandle()	{	return m_webSocketHandle;	}
	void	setWebSocketHandle(const WebSocketHandle & handle)	{   m_isWebSocket = true; m_webSocketHandle = handle; }

	const bool & isWebSocket()	{	return m_isWebSocket;	}

	//IP 工具类
	//转换URI字符串为 sockaddr_in 格式  字符串格式为 [::ffff:127.0.0.1]:33642 或者 127.0.0.1:1233
	static sockaddr_in  getStringAddrToSockaddr(const String & strAddr); 		
	//初始化WebSocket 
	void InitWebSocket(const WebSocketHandle & handle , size_t readbuffersize = 0 , size_t writebuffersize = 0);
	//初始化WebSocket 
	void InitWebSocketTLS(const WebSocketHandle & handle , size_t readbuffersize = 0 , size_t writebuffersize = 0);

	void setWebSocketUserAgent(const String & agent)  	{  m_webSocketUserAgent = agent; }
	const String & getWebSocketUserAgent(void)		{  return m_webSocketUserAgent;	}

	bool	WebSocketRead(const String & msg);
	bool	OnWebSocketRead(const String & msg);
	bool	WebSocketWrite(const void * data, size_t len);
	bool	OnWebSocketWrite(const String &msg);

	//是否安全套接字
	const bool & isTLS()		{	return m_tls;	}

	//Socket 是否进行强制关闭
	const bool & isForceClose()	{	return m_force_close;	}
	void	setForceClose(const bool & set)		{	m_force_close  = set ; }
protected:

	void	initialize(void);

	uint32	  m_last_timer;
	//命令执行的最小间隔时间(默认200ms) 每秒最多5条指令
	uint32	  m_run_timer;
	//Socket执行超时的时间间隔  默认是30's
	uint32   m_timeout_timer;

	//虚拟IP地址
	String	m_fakeIP;

	AtomicScalar<SOCKET_STATUS>  m_socket_status;
        SOCKET_TYPE             m_socket_type;

	Threading::AtomicCounter m_writeLock;

	bool		m_packetAvailed;
	bool		m_isThreadQueued;

	bool		m_secondAuth;
	uint32		m_secondAuthTime;

	sockaddr_in 	m_addr;
	bool		m_deleted;
	bool		m_checkTimeout;

	bool		m_tls;
	//Socket Force Close
	bool		m_force_close;        
	
	//发送总数据
	size_t		m_sendedSize;
	//压缩后数据
	size_t		m_compressSize;

	//接收总数据
        size_t          m_readSize;

	//是否为 WEBSocket
	bool		m_isWebSocket;
	//WebSocket Handle
	WebSocketHandle	m_webSocketHandle;

	//Web Socket 扩展信息
	String		m_webSocketUserAgent;
	//WEB Socket 缓冲
	String		m_webSocketReadBuffer;
	String		m_webSocketWriteBuffer;

};

  /** Specialisation of SharedPtr to allow SharedPtr to be assigned to ArmyPtr 
    @note Has to be a subclass since we need operator=.
    We could templatise this instead of repeating per Resource subclass, 
    except to do so requires a form VC6 does not support i.e.
    ResourceSubclassPtr<T> : public SharedPtr<T>
    */
    class SERVER_DECL WSSocketPtr : public SharedPtr<WSSocket>
    {
    public:
        WSSocketPtr() : SharedPtr<WSSocket>() {}
        explicit WSSocketPtr(WSSocket* rep) : SharedPtr<WSSocket>(rep) {}
        WSSocketPtr(const WSSocketPtr& r) : SharedPtr<WSSocket>(r) {}
        WSSocketPtr(const ResourcePtr& r);
        /// Operator used to convert a ResourcePtr to a MeshPtr
        WSSocketPtr& operator=(const ResourcePtr& r);
    protected:
        /// Override destroy since we need to delete Mesh after fully defined
        void destroy(void);
    };
	




#endif
